﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;

using Framework.Graphics;

namespace Framework.Map
{
    public class TileMap
    {
        #region Variablen

        // Loads contents 
        private ContentManager _contentManager;

        // Map size in tiles
        private int _mapWidth;
        private int _mapHeight;

        // Tile size in pixel
        private int _tileWidth;
        private int _tileHeight;

        // All textures
        private List<Texture2D> _texture = new List<Texture2D>();

        // All tiles of the map
        private Tile[,] _allTiles;

        #endregion

        #region Accessoren

        public int MapWidth
        {
            get { return _mapWidth; }
            set { _mapWidth = value; }
        }

        public int MapHeight
        {
            get { return _mapHeight; }
            set { _mapHeight = value; }
        }

        public int TileWidth
        {
            get { return _tileWidth; }
            set { _tileWidth = value; }
        }

        public int TileHeight
        {
            get { return _tileHeight; }
            set { _tileHeight = value; }
        }

        public Tile[,] AllTiles
        {
            get { return _allTiles; }
            set { _allTiles = value; }
        }

        #endregion

        #region Methods

        public void Initalisieren(ContentManager cm, string mapname)
        {
            _contentManager = cm;

            string fullPath = @"Content/Levels/" + mapname + @"/";
            string contentPath = @"Levels/" + mapname + @"/";

            StreamReader SR = new StreamReader(fullPath + "MapInfo.txt");

            /*
             * Construction of the MapInfo file
             * Tiles X
             * Tiles Y
             * Number of textures
             * Texture 1 Name ...
             */
            _mapHeight = 30;
            _mapWidth = Convert.ToInt32(SR.ReadLine());
            //_mapHeight = Convert.ToInt32(SR.ReadLine());

            SR.ReadLine();

            _allTiles = new Tile[_mapWidth, _mapHeight];

            int tempNumTex = Convert.ToInt32(SR.ReadLine());

            for (int i = 0; i < tempNumTex; i++)
            {
                _texture.Add(cm.Load<Texture2D>(contentPath + @"Texture/" + (SR.ReadLine())));
            }

            SR.Close();

            StreamReader dirrectionReader = new StreamReader(fullPath + "Direction.txt");
            StreamReader enterableReader = new StreamReader(fullPath + "Enterable.txt");
            StreamReader mapReader = new StreamReader(fullPath + "MapLayer1.txt");

            for (int y = 0; y < _mapHeight; y++)
            {         
                string[] tempDirrection = dirrectionReader.ReadLine().Split(new char[] { ',', });
                string[] tempEnterable = enterableReader.ReadLine().Split(new char[] { ',', });
                string[] tempMap = mapReader.ReadLine().Split(new char[] { ',', });

                for (int x = 0; x < _mapWidth; x++)
                {
                    Int32 dirrection = Convert.ToInt32(tempDirrection[x]);
                    Int32 map = Convert.ToInt32(tempMap[x]);
                    bool enterable = false;
                    if (tempEnterable[x] == "1" || tempEnterable[x] == "01")
                    {
                        enterable = true;
                    }
                    if (tempEnterable[x] == "0" || tempEnterable[x] == "00")
                    {
                        enterable = false;
                    }

                    Tile tempTile = new Tile(x, y, enterable, map);

                    _allTiles[x, y] = tempTile;

                    GC.Collect();
                }
            }

            dirrectionReader.Close();
            enterableReader.Close();
            mapReader.Close();

        }

        public void Draw()
        {
            for (int y = 0; y < _mapHeight; y++)
            {
                for (int x = 0; x < _mapWidth; x++)
                {
                    Camera.TryDraw(_texture[_allTiles[x, y].Texture], new Vector2(x * _tileWidth, y * _tileHeight), Color.White);
                }
            }
        }

        public void DrawGround()
        {
            for (int y = 0; y < _mapHeight; y++)
            {
                for (int x = 0; x < _mapWidth; x++)
                {
                    if(_allTiles[x,y].TileEnterable == true)
                        Camera.TryDraw(_texture[_allTiles[x, y].Texture], new Vector2(x * _tileWidth, y * _tileHeight), null, Color.White,
                            0f, new Vector2(x * _tileWidth, y * _tileHeight), 0.5f, SpriteEffects.None, 0f);
                }
            }
        }

        public void DrawScene()
        {
            for (int y = 0; y < _mapHeight; y++)
            {
                for (int x = 0; x < _mapWidth; x++)
                {
                    if (_allTiles[x, y].TileEnterable == false)
                        Camera.TryDraw(_texture[_allTiles[x, y].Texture], new Vector2(x * _tileWidth, y * _tileHeight), null, Color.White,
                            0f, new Vector2(x * _tileWidth, y * _tileHeight),0.5f,SpriteEffects.None,0f);
                    //Camera.TryDraw(Map.TextureMapTexture[Map.TextureMap[x, y]], Temp, null, Color.White, 0f, Temp, 0.5f, SpriteEffects.None, 0f);
                }
            }
        }

        public static int DistanzBestimmenINT(Tile Objekt1, Tile Objekt2)
        {
            int Distanz;
            int XDistanz = 0;
            int YDistanz = 0;

            #region Abstand Links Rechts

            // Wenn 1 Rechts von 2 liegt
            if (Objekt1.TileX > Objekt2.TileX)
            {
                XDistanz = Objekt1.TileX - Objekt2.TileX;
            }
            // Wenn 1 Links von 2 liegt
            if (Objekt1.TileX > Objekt2.TileX)
            {
                XDistanz = Objekt2.TileX - Objekt1.TileX;
            }
            // Wenn 1 auf gleicher Ober / Unter 2 Liegt
            if (Objekt1.TileX > Objekt2.TileX)
            {
                XDistanz = 0;
            }

            #endregion

            #region Abstand Oben Unten
            //Wenn 1 ober 2 liegt
            if (Objekt1.TileY < Objekt2.TileY)
            {
                YDistanz = Objekt2.TileY - Objekt1.TileY;
            }
            //Wenn 1 unter 2 liegt
            if (Objekt1.TileY > Objekt2.TileY)
            {
                YDistanz = Objekt1.TileY - Objekt2.TileY;
            }
            //Wenn 1 und 2 auf gleicher Höhe liegen
            if (Objekt1.TileY == Objekt2.TileY)
            {
                YDistanz = 0;
            }
            #endregion

            Distanz = XDistanz + YDistanz;
            return Distanz;
        }

        public Tile GetTileByPosInFieldSize(Vector2 VPosInFieldSize)
        {

            if (VPosInFieldSize.X < 0 || VPosInFieldSize.Y < 0 || VPosInFieldSize.X >= _mapWidth || VPosInFieldSize.Y >= _mapHeight)
            {
                return null;
            }

            return _allTiles[(int)VPosInFieldSize.X, (int)VPosInFieldSize.Y];
        }

        public Texture2D Texture(int x, int y)
        {
            return _texture[_allTiles[x, y].Texture];
        }

        #endregion
    }
}
